// -----------------------------------------------------------------------
//  <copyright file="MapFromAndMapToProfile.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2022 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://www.dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2022-12-09 18:49</last-date>
// -----------------------------------------------------------------------

using DaprPlus.AutoMapper.Properties;


namespace DaprPlus.AutoMapper;

/// <summary>
/// 创建源类型与目标类型的映射配对
/// </summary>
public class MapFromAndMapToProfile : AutoMapperTupleBase
{
    private readonly ILogger _logger;
    private readonly DaprPlusContext _daprPlusContext;

    /// <summary>
    /// 初始化一个<see cref="MapFromAndMapToProfile"/>类型的新实例
    /// </summary>
    public MapFromAndMapToProfile(IServiceProvider provider)
    {
        _logger = provider.GetLogger<MapFromAndMapToProfile>();
        _daprPlusContext = provider.GetRequiredService<DaprPlusContext>();
    }

    /// <summary>
    /// 获取 排序
    /// </summary>
    public override int Order => -9999;

    /// <summary>
    /// 执行对象映射构造
    /// </summary>
    public override void CreateMap()
    {
        var tuples = new List<(Type Source, Type Target)>();

        var types = _daprPlusContext.FindTypesByAttribute<MapFromAttribute>();
        foreach (var targetType in types)
        {
            var attribute = targetType.GetAttribute<MapFromAttribute>(true);
            foreach (var sourceType in attribute.SourceTypes)
            {
                var tuple = ValueTuple.Create(sourceType, targetType);
                tuples.AddIfNotExist(tuple);
            }
        }

        types = _daprPlusContext.FindTypesByAttribute<MapToAttribute>();
        foreach (var sourceType in types)
        {
            var attribute = sourceType.GetAttribute<MapToAttribute>(true);
            foreach (var targetType in attribute.TargetTypes)
            {
                var tuple = ValueTuple.Create(sourceType, targetType);
                tuples.AddIfNotExist(tuple);
            }
        }

        foreach (var (source, target) in tuples)
        {
            CreateMap(source, target);
            _logger.LogDebug(ResAutoMapper.Format_Mapping_From_To, source, target);
        }
        _logger.LogInformation(ResAutoMapper.Format_Mapping_Count, tuples.Count);
    }
}
